﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Web.UI.WebControls;
using System.Drawing;


namespace FlexiPay
{
    public class MatrixMaster
    {
        #region member variables - private
        private int SlabId = 0;
        private int rowCount = 0;
        private int colCount = 0;
        private DataTable dt;
        private TextBox[,] tbSlab;
        private DataTable flatDt;
        #endregion

        #region getters
        public int getRowCount() { return rowCount; }
        public int getColumnCount() { return colCount; }
        public int getSlabId() { return SlabId; }
        public DataTable getMatrix2DT() { return dt; }
        public TextBox[,] getMatrix2TB() { return tbSlab; }
        #endregion

        #region constuctor - new matrix
        //this is new slab id create request
        public MatrixMaster(int si, int rows, int columns)
        {
            //set dimensions 
            SlabId = si;
            rowCount = rows;
            colCount = columns;

            //create blank
            Initialize2D();
            createFlat();
        }

        //set all values to zero
        private void Initialize2D()
        {
            dt = new DataTable();
            tbSlab = new TextBox[rowCount + 1, colCount + 1];

            //create columns
            for (int i = 0; i <= colCount; i++)
                dt.Columns.Add("C" + i.ToString());
            //create rows
            for (int i = 0; i <= rowCount; i++)
                dt.Rows.Add("R" + i.ToString());

            //set zero values
            for (int i = 0; i <= rowCount; i++)
            {
                for (int j = 0; j <= colCount; j++)
                {
                    Boolean isHeader = false;
                    if (colCount == 1)
                        isHeader = (j == 0);
                    else
                        isHeader = ((i == 0) || (j == 0));
                    tbSlab[i, j] = getTextBox(isHeader);
                    tbSlab[i, j].Text = "0";
                    dt.Rows[i][j] = "0";
                }
            }

            dt.AcceptChanges();
        }

        //create flat with zero values
        private void createFlat()
        {
            flatDt = new DataTable();

            //create columns
            flatDt.Columns.Add("SlabId");
            flatDt.Columns.Add("RowNo");
            flatDt.Columns.Add("ColumnNo");
            flatDt.Columns.Add("Value");

            //populate datatable with default values
            for (int i = 0; i <= rowCount; i++)
            {
                for (int j = 0; j <= colCount; j++)
                {
                    DataRow dr = flatDt.NewRow();
                    dr["SlabID"] = SlabId;
                    dr["RowNo"] = i;
                    dr["ColumnNo"] = j;
                    dr["Value"] = 0;
                    flatDt.Rows.Add(dr);
                }
            }
            flatDt.AcceptChanges();
            //GlobalMethods.uploadDT2DB(dt, "SlabValues");
        }
        #endregion

        #region constructor - existing matrix
        //this is retrieval request
        public MatrixMaster(int si)
        {
            SlabId = si;
            RetrieveDimension();
            RetrieveDBValues();
            Initialize2D();
            ConvertFlat2Matrix();
        }

        //get dimension of existing matrix
        private void RetrieveDimension()
        {
            string rowCmd = "Select Max(RowNo) from SlabValues where SlabId = '" + SlabId.ToString() + "'";
            string colCmd = "Select Max(ColumnNo) from SlabValues where SlabId = '" + SlabId.ToString() + "'";

            string rows = DataBaseMethods.ExecuteScalar(rowCmd);
            string cols = DataBaseMethods.ExecuteScalar(colCmd);

            try
            {
                rowCount = Convert.ToInt32(rows);
                colCount = Convert.ToInt32(cols);
            }
            catch (Exception)
            {
                throw new Exception("Slab does not exist.");
            }

            if ((rowCount < 1) || (colCount < 1))
                throw new Exception("Invalid Slab Dimensions");
        }

        //get flat values
        private void RetrieveDBValues()
        {
            //select command
            string selectCmd = "Select SlabId, RowNo, ColumnNo, Value from SlabValues where SlabId = '" + SlabId.ToString() + "' Order By RowNo, ColumnNo ";

            //get slab values - flat structure
            flatDt = DataBaseMethods.ExecuteSelectQuery(selectCmd);
        }

        private TextBox getTextBox(bool header)
        {
            TextBox tb = new TextBox();
            tb.Height = 25;
            tb.Width = 60;
            tb.BorderWidth = 2;
            if (header) tb.BackColor = Color.Aqua;
            return tb;
        }
        #endregion

        #region converts matrix v/s flat
        //convert flat to matrix
        private void ConvertFlat2Matrix()
        {
            foreach (DataRow dr in flatDt.Rows)
            {
                dt.Rows[Convert.ToInt32(dr[1].ToString())][Convert.ToInt32(dr[2].ToString())] = dr[3].ToString();
                tbSlab[Convert.ToInt32(dr[1].ToString()), Convert.ToInt32(dr[2].ToString())].Text = dr[3].ToString();
            }
        }

        public void convertMatrix2Flat()
        {
            foreach (DataRow dr in flatDt.Rows)
            {
                int row = Convert.ToInt32(dr.Table.Rows[0][1].ToString());
                int col = Convert.ToInt32(dr.Table.Rows[0][2].ToString());
                dr.Table.Rows[0][3] = dt.Rows[row][col].ToString();
                //tbSlab[Convert.ToInt32(dr[1].ToString()), Convert.ToInt32(dr[2].ToString())].Text = dr[3].ToString();
            }
        }
        #endregion

        #region update operations
        public void updateDB()
        {
            DataBaseMethods.uploadDT2DB(flatDt, "SlabValues");
        }

        //uplodate matrix from datatable
        public void updateMatrix(DataTable inputdt)
        {
            for (int i = 0; i <= rowCount; i++)
            {
                for (int j = 0; j <= colCount; j++)
                {
                    tbSlab[i, j].Text = inputdt.Rows[i][j].ToString();
                    dt.Rows[i][j] = inputdt.Rows[i][j].ToString();
                }
            }
            convertMatrix2Flat();
        }

        //uplodate matrix from text boxes
        public void updateMatrix(TextBox[,] inputTb)
        {
            for (int i = 0; i <= rowCount; i++)
            {
                for (int j = 0; j <= colCount; j++)
                {
                    tbSlab[i, j].Text = inputTb[i, j].ToString();
                    dt.Rows[i][j] = inputTb[i, j].ToString();
                }
            }
            convertMatrix2Flat();
        }
        #endregion

    }
}